# !/usr/bin/python
# -*- coding: utf-8 -*-

# THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW: 
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),  
# to deal in the Software without restriction, including without limitation  
# the rights to use, copy, modify, merge, publish, distribute, sublicense,  
# and/or sell copies of the Software, and to permit persons to whom the  
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in 
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
# DEALINGS IN THE SOFTWARE.

# playing.py
# written by: 
#     Jan Jokela <jan@devion.org>

import sys, os
from qgl import scene
import base.config.config as config
import base.config.data as config_data
from fluid.eye import *
import fluid.actions as actions
import fluid.visuals as visuals
import data
import base.background as background
import base.topbar as topbar


class MusicPlaying(object):
    def __init__(self):
        self.audio = data.audio
        eventhandler.subscribe(self)
        self.topbar = topbar.TopBar(self)
        self.background = background.Background()
        self.album_art_view = AlbumArtView(self.audio)
        self.toolbar = ToolBar(self)
        self.audio_info = AudioInfo()
        self.track_bar = TrackBar(self)
        
        self.audio_player = data.audio_player
        if self.audio_player.get_media() != self.audio.uri:
            print self.audio_player.get_media()
            print self.audio
            self.audio_player.stop()
        self.audio_player.play(str(self.audio.uri))
        
    def handle_events(self, events):
        if config.input == "keyboard + mouse":
            for event in events:
                if event.type is KEYUP:
                    if event.key == K_RETURN:
                        self.destroy()
                        eventhandler.clear()
                        if data.nav == "albums":
                            import album
                            album.MusicAlbum()
                        elif data.nav == "artists":
                            import artist
                            artist.MusicArtist()
                        elif data.nav == "genres":
                            import genre
                            genre.MusicGenre()
                        root_node.accept(compiler)   
                        
    def destroy(self):
        eventhandler.unsubscribe(self)
        self.topbar.destroy()
        self.background.destroy()
        self.audio_info.destroy()
        self.album_art_view.destroy()
        self.track_bar.destroy()
        self.toolbar.destroy()
 
  
class AlbumArtView(object):
    def __init__(self, album):
        self.album = album
        for item in data.audio_library:
            if item.album == self.album:
                self.album = item
        self.draw()
    def draw(self):
        
        # the shared color for the album art and its reflex
        self.color = qgl.scene.state.Color((1.0,1.0,1.0,0.0))
        # the album art
        img = self.album.album_art
        if img != '':
            tex = qgl.scene.state.Texture(img)
            quad = qgl.scene.state.Quad((14,14))
            self._w_album_art = qgl.scene.Group()
            self._w_album_art.add(tex, self.color, quad)
            self._w_album_art.translate = (-19.5,4,-45)
            viewport.add(self._w_album_art)
            self._w_album_art.axis = (0.0,1.0,0.0)
            #self.Walbumart.angle = 30    
        else: 
            img = os.path.join(config_data.theme, 'music-unknown-album.png')
            tex = qgl.scene.state.Texture(img)
            quad = qgl.scene.state.Quad((14,14))
            self._w_album_art = qgl.scene.Group()
            self._w_album_art.add(tex, self.color, quad)
            self._w_album_art.translate = (-19.5,4,-45)
            viewport.add(self._w_album_art)

        img = visuals.reflex(img, intensity=25)
        tex = qgl.scene.state.Texture(img)
        quad = qgl.scene.state.Quad((14,14))
        self._w_album_art_reflex = qgl.scene.Group()
        self._w_album_art_reflex.add(tex, self.color, quad)
        self._w_album_art_reflex.translate = (-19.5,-10,-45)
        viewport.add(self._w_album_art_reflex)
        actions.Fade(self.color, alpha=1.0, time=3.0)

    def destroy(self):
        viewport.remove(self._w_album_art)
        viewport.remove(self._w_album_art_reflex)
            
        
class AudioInfo(object):
    def __init__(self):
        eventhandler.subscribe(self)
        self.audio = data.audio
        self.draw()
    def draw(self):
        if str(self.audio.title) == 'None' or str(self.audio.title) == "" or str(self.audio.title) == "Unknown":
            text = qgl.scene.state.Text("Unknown track", config_data.fonts + "/URWGothicL.ttf", (0.8, 0.8, 0.8), None, 34)
        else: text = qgl.scene.state.Text(str(self.audio.title), config_data.fonts + "/URWGothicL.ttf", (0.8, 0.8, 0.8), None, 34)
        self._w_title = qgl.scene.Group()
        self._w_title.add(text)
        self._w_title.axis = (0.0,1.0,0.0)
        if config.input == "touchscreen" or (config.input == "keyboard + mouse" and mousehandler.active()):
            self._w_title.translate = (-4,4,-23)
            self._w_title.angle = 0.0             
        else:
            self._w_title.translate = (-2,2,-23)
            self._w_title.angle = -30.0   
            print 'angle is: ' + str(self._w_title.angle)
        viewport.add(self._w_title)
        
        if str(self.audio.album) == 'None' or str(self.audio.album) == "" or str(self.audio.album) == "Unknown":
            text = qgl.scene.state.Text("Unknown album", config_data.fonts + "/URWGothicL.ttf", (0.8, 0.8, 0.8), None, 28)
        else: text = qgl.scene.state.Text(str(self.audio.album), config_data.fonts + "/URWGothicL.ttf", (0.8, 0.8, 0.8), None, 28)
        self._w_album = qgl.scene.Group()
        self._w_album.add(text)
        self._w_album.axis = (0.0,1.0,0.0)
        if config.input == "touchscreen" or (config.input == "keyboard + mouse" and mousehandler.active()):
            self._w_album.translate = (-4,2,-23)
            self._w_album.angle = 0.0   
        else:
            self._w_album.translate = (-2,0,-23)
            self._w_album.angle = -30.0   
        viewport.add(self._w_album) 
                
        if str(self.audio.artist) == 'None' or str(self.audio.artist) == "" or str(self.audio.artist) == "Unknown":
            text = qgl.scene.state.Text("Unknown artist", config_data.fonts + "/URWGothicL.ttf", (0.8, 0.8, 0.8), None, 26)
        else: text = qgl.scene.state.Text(str(self.audio.artist), config_data.fonts + "/URWGothicL.ttf", (0.8, 0.8, 0.8), None, 26)
        self._w_artist = qgl.scene.Group()
        self._w_artist.add(text)
        self._w_artist.axis = (0.0,1.0,0.0)
        if config.input == "touchscreen" or (config.input == "keyboard + mouse" and mousehandler.active()):
            self._w_artist.translate = (-4,0,-23)
            self._w_artist.angle = 0.0           
        else:
            self._w_artist.translate = (-2,-2,-23)
            self._w_artist.angle = -30.0   
        viewport.add(self._w_artist)
        
    def handle_events(self, events):
        if config.input == "keyboard + mouse":
            for event in events: 
                if event.type == 'mouse_active':
                    print 'mouse is active'
                    actions.Rotate(self._w_title, (0.0,1.0,0.0), 0, .5)
                    actions.Rotate(self._w_album, (0.0,1.0,0.0), 0, .5)
                    actions.Rotate(self._w_artist, (0.0,1.0,0.0), 0, .5)
                    actions.Move(self._w_title, (-4,4,-23), .5)
                    actions.Move(self._w_album, (-4,2,-23), .5)
                    actions.Move(self._w_artist, (-4,0,-23), .5)
                if event.type == 'mouse_inactive':
                    print 'mouse is inactive'
                    actions.Rotate(self._w_title, (0.0,1.0,0.0), -30, .5)
                    actions.Rotate(self._w_album, (0.0,1.0,0.0), -30, .5)
                    actions.Rotate(self._w_artist, (0.0,1.0,0.0), -30, .5)
                    actions.Move(self._w_title, (-2,2,-23), .5)
                    actions.Move(self._w_album, (-2,0,-23), .5)
                    actions.Move(self._w_artist, (-2,-2,-23), .5)                      
        
    def destroy(self):
        eventhandler.unsubscribe(self)
        viewport.remove(self._w_title)
        viewport.remove(self._w_album)
        viewport.remove(self._w_artist)
        
class AlbumArtView(object):
    def __init__(self, audio):
        self.audio = audio
        eventhandler.subscribe(self)
        self.mouse_active = None
        for item in data.audio_library:
            if item.title == self.audio:
                self.audio = item
        self.draw()
    def draw(self):
        
        # the shared color for the album art and its reflex
        self.color = qgl.scene.state.Color((1.0,1.0,1.0,0.0))
        # the album art
        img = self.audio.album_art
        if img == '': img = os.path.join(config_data.theme, 'music-unknown-album.png')
        tex = qgl.scene.state.Texture(img)
        quad = qgl.scene.state.Quad((14,14))
        self._w_album_art = qgl.scene.Group()
        self._w_album_art.add(tex, self.color, quad)
        self._w_album_art.axis = (0.0,1.0,0.0)
        if config.input == "touchscreen" or (config.input == "keyboard + mouse" and mousehandler.active()):
            self._w_album_art.translate = (-14,1,-35)
            self._w_album_art.angle = 70.0               
        else:
            self._w_album_art.translate = (-12,1,-35)
            self._w_album_art.angle = 30.0   
        viewport.add(self._w_album_art) 
           
        self.color_reflex = qgl.scene.state.Color((1.0,1.0,1.0,0.0))
        img = visuals.reflex(img, intensity=25)
        tex = qgl.scene.state.Texture(img)
        quad = qgl.scene.state.Quad((14,14))
        self._w_album_art_reflex = qgl.scene.Group()
        self._w_album_art_reflex.add(tex, self.color_reflex, quad)
        self._w_album_art_reflex.axis = (0.0,1.0,0.0)
        if config.input == "touchscreen" or (config.input == "keyboard + mouse" and mousehandler.active()):
            self._w_album_art_reflex.translate = (-14,-13,-35)
            self._w_album_art_reflex.angle = 70.0               
        else:
            self._w_album_art_reflex.translate = (-12,-13,-35)
            self._w_album_art_reflex.angle = 30.0   
        viewport.add(self._w_album_art_reflex)
        
        actions.Fade(self.color, alpha=1.0, time=3.0)
        actions.Fade(self.color_reflex, alpha=0.5, time=3.0)

    def handle_events(self, events):
        if config.input == "keyboard + mouse":
            for event in events: 
                if event.type == 'mouse_active':
                    if self.mouse_active != None:
                        if not self.rot_album_art.finished: self.rot_album_art.stop()
                        if not self.rot_album_art_reflex.finished: self.rot_album_art.stop()
                        if not self.mov_album_art.finished: self.rot_album_art.stop()
                        if not self.mov_album_art_reflex.finished: self.rot_album_art.stop()
                    self.rot_album_art = actions.Rotate(self._w_album_art, (0.0,1.0,0.0), 70, 0.5)
                    self.rot_album_art_reflex = actions.Rotate(self._w_album_art_reflex, (0.0,1.0,0.0), 70, 0.5)
                    self.mov_album_art = actions.Move(self._w_album_art, (-14,1,-35), 0.5)
                    self.mov_album_art_reflex = actions.Move(self._w_album_art_reflex, (-14,-13,-35), 0.5)
                    self.mouse_active = True
                elif event.type == 'mouse_inactive':
                    if self.mouse_active != None:
                        if not self.rot_album_art.finished: self.rot_album_art.stop()
                        if not self.rot_album_art_reflex.finished: self.rot_album_art.stop()
                        if not self.mov_album_art.finished: self.rot_album_art.stop()
                        if not self.mov_album_art_reflex.finished: self.rot_album_art.stop()
                    self.rot_album_art = actions.Rotate(self._w_album_art, (0.0,1.0,0.0), 30, 0.5)
                    self.rot_album_art_reflex = actions.Rotate(self._w_album_art_reflex, (0.0,1.0,0.0), 30, 0.5)
                    self.mov_album_art = actions.Move(self._w_album_art, (-12,1,-35), 0.5)
                    self.mov_album_art_reflex = actions.Move(self._w_album_art_reflex, (-12,-13,-35), 0.5)
                    self.mouse_active = False
                    
    def destroy(self):
        viewport.remove(self._w_album_art)
        viewport.remove(self._w_album_art_reflex)

class ToolBar(object):
    def __init__(self, parent):
        self.parent = parent
        eventhandler.subscribe(self)  
        self.draw()
    def draw(self):
        self.color = qgl.scene.state.Color((1.0,1.0,1.0,0.0))
        img = os.path.join(config_data.theme, 'previous.png')
        tex = qgl.scene.state.Texture(img)
        quad = qgl.scene.state.Quad((4,4))
        self._w_previous = qgl.scene.Group()
        self._w_previous.add(tex, self.color, quad)
        self._w_previous.translate = (-4,-5,-35)
        self._w_previous.selectable = True
        viewport.add(self._w_previous)          
        
        img = os.path.join(config_data.theme, 'play.png')
        tex = qgl.scene.state.Texture(img)
        quad = qgl.scene.state.Quad((4,4))
        self._w_play = qgl.scene.Group()
        self._w_play.add(tex, self.color, quad)
        self._w_play.translate = (0,-5,-35)
        self._w_play.selectable = True
        if data.audio_player.get_paused(): viewport.add(self._w_play)  
        
        img = os.path.join(config_data.theme, 'pause.png')
        tex = qgl.scene.state.Texture(img)
        quad = qgl.scene.state.Quad((4,4))
        self._w_pause = qgl.scene.Group()
        self._w_pause.add(tex, self.color, quad)
        self._w_pause.translate = (0,-5,-35)
        self._w_pause.selectable = True
        if not data.audio_player.get_paused(): viewport.add(self._w_pause)     
        
        img = os.path.join(config_data.theme, 'next.png')
        tex = qgl.scene.state.Texture(img)
        quad = qgl.scene.state.Quad((4,4))
        self._w_next = qgl.scene.Group()
        self._w_next.add(tex, self.color, quad)
        self._w_next.translate = (4,-5,-35)
        self._w_next.selectable = True
        viewport.add(self._w_next) 
    
        if config.input == "toucscreen" or (config.input == "keyboard + mouse" and mousehandler.active()):
            actions.Fade(self.color, alpha=1.0, time=.5)
    
    def handle_events(self, events):
        if config.input == "keyboard + mouse":
            for event in events: 
                if event.type == 'mouse_active':
                    actions.Fade(self.color, alpha=1.0, time=.5)
                elif event.type == 'mouse_inactive':
                    actions.Fade(self.color, alpha=0.0, time=.5)
                elif event.type == MOUSEBUTTONDOWN and mousehandler.active():
                    picker.set_position(event.pos)
                    root_node.accept(compiler)
                    root_node.accept(picker)          
                    if self._w_pause in picker.hits:
                        data.audio_player.pause()
                        viewport.remove(self._w_pause)
                        viewport.add(self._w_play)
                    if self._w_play in picker.hits:
                        data.audio_player.play(str(data.audio.uri))
                        viewport.remove(self._w_play)
                        viewport.add(self._w_pause)
                    if self._w_previous in picker.hits:
                        eventhandler.clear()
                        self.parent.destroy()
                        print data.playlist.get_previous(data.audio).title
                        data.audio = data.playlist.get_previous(data.audio)
                        MusicPlaying()
                        root_node.accept(compiler)                    
                    if self._w_next in picker.hits:
                        eventhandler.clear()
                        self.parent.destroy()
                        print data.playlist.get_next(data.audio).title
                        data.audio = data.playlist.get_next(data.audio)
                        MusicPlaying()
                        root_node.accept(compiler)
                    
    def destroy(self):
        eventhandler.unsubscribe(self)
        viewport.remove(self._w_previous) 
        print data.audio_player.get_paused()
        if data.audio_player.get_paused(): 
            viewport.remove(self._w_play)
        else: viewport.remove(self._w_pause)
        viewport.remove(self._w_next)    
    
class TrackBar(object):
    def __init__(self, parent):
        self.parent = parent
        eventhandler.subscribe(self)
        self.audio_player = data.audio_player
        self.time_played = '00:00'
        self.time_remaining = '-00:00'
        self.draw()
        self.update()
    def draw(self):
        self.color = qgl.scene.state.Color((1.0,1.0,1.0,0.0))
        
        img = os.path.join(config_data.theme, 'music-trackbar.png')
        tex = qgl.scene.state.Texture(img)
        quad = qgl.scene.state.Quad((22,1))
        self._w_track_bar = qgl.scene.Group()
        self._w_track_bar.add(tex, self.color, quad)
        self._w_track_bar.translate = (0,-6.25,-17.5)
        viewport.add(self._w_track_bar)
        
        img = os.path.join(config_data.theme, 'music-trackpos.png')
        tex = qgl.scene.state.Texture(img)
        quad = qgl.scene.state.Quad((0.6,0.6))
        self._w_track_pos = qgl.scene.Group()
        self._w_track_pos.add(tex, self.color, quad)
        # -10.5, 10.5
        self._w_track_pos.translate = (-10.5,-6.25,-17.5)
        viewport.add(self._w_track_pos)
        
        text = qgl.scene.state.Text(str(self.time_played), config_data.fonts + "/URWGothicL.ttf", (0.8, 0.8, 0.8), None, 28)
        self._w_time_played = qgl.scene.Group()
        self._w_time_played.add(self.color, text)
        self._w_time_played.translate = (-15.5,-8.1,-25.0)
        viewport.add(self._w_time_played)
  
        text = qgl.scene.state.Text(str(self.time_remaining), config_data.fonts + "/URWGothicL.ttf", (0.8, 0.8, 0.8), None, 28)
        self._w_time_remaining = qgl.scene.Group()
        self._w_time_remaining.add(self.color, text)
        self._w_time_remaining.translate = (12.5,-8.1,-25.0)
        viewport.add(self._w_time_remaining)
        
        actions.Fade(self.color, alpha=1.0, time=3.0)
        self.Amove = None
        
    def update(self):
        if not self.audio_player.get_position() == 0 or self.audio_player.get_duration():
            self._w_track_pos.translate = (-10.5 + (self.audio_player.get_position()*21.0/self.audio_player.get_duration()),-6.25,-17.5)
        
        if not self.audio_player.get_position() == 0 or self.audio_player.get_duration():
            _time_played = self.convert_ns(self.audio_player.get_position()*1000000)
            _time_remaining =  '-' + self.convert_ns(self.audio_player.get_duration()*1000000 - self.audio_player.get_position()*1000000)
            #print self.audio_player.get_duration()
        else: 
            _time_played = '00:00'
            _time_remaining = '-00:00'
        if self.time_played != _time_played:
            self.time_played = _time_played
            viewport.remove(self._w_time_played)
            text = qgl.scene.state.Text(str(self.time_played), config_data.fonts + "/URWGothicL.ttf", (0.8, 0.8, 0.8), None, 28)
            self._w_time_played = qgl.scene.Group()
            self._w_time_played.add(self.color, text)
            self._w_time_played.translate = (-15.5,-8.1,-25.0)
            viewport.add(self._w_time_played)
        if self.time_remaining != _time_remaining:
            self.time_remaining = _time_remaining    
            viewport.remove(self._w_time_remaining)      
            text = qgl.scene.state.Text(str(self.time_remaining), config_data.fonts + "/URWGothicL.ttf", (0.8, 0.8, 0.8), None, 28)
            self._w_time_remaining = qgl.scene.Group()
            self._w_time_remaining.add(self.color, text)
            self._w_time_remaining.translate = (12.5,-8.1,-25.0)
            viewport.add(self._w_time_remaining)
        #print self.audio_player.get_position()
        #print self.audio_player.get_duration()
        #print self.audio_player.get_paused()
        if (self.audio_player.get_duration() - self.audio_player.get_position()) < 500 and self.audio_player.get_duration() != 0:
            self.parent.destroy()
            eventhandler.clear()
            print data.playlist.get_next(data.audio).title
            data.audio = data.playlist.get_next(data.audio)
            MusicPlaying()
            root_node.accept(compiler)
        
    def convert_ns(self, time_int):
        time_int = time_int / 1000000000
        time_str = ""
        if time_int >= 3600:
            _hours = time_int / 3600
            time_int = time_int - (_hours * 3600)
            time_str = str(_hours) + ":"
        if time_int >= 600:
            _mins = time_int / 60
            time_int = time_int - (_mins * 60)
            time_str = time_str + str(_mins) + ":"
        elif time_int >= 60:
            _mins = time_int / 60
            time_int = time_int - (_mins * 60)
            time_str = time_str + "0" + str(_mins) + ":"
        else:
            time_str = time_str + "00:"
        if time_int > 9:
            time_str = time_str + str(time_int)
        else:
            time_str = time_str + "0" + str(time_int)
            
        return time_str
        
    def handle_events(self, events):
        self.update()
        if config.input == "keyboard + mouse":
            for event in events: 
                if event.type is KEYUP:
                    if event.key == K_LEFT:
                        self.audio_player.seek(self.audio_player.get_position()*1000000 - (self.audio_player.get_duration()*20/180)*1000000)
                    elif event.key == K_RIGHT:
                        self.audio_player.seek(self.audio_player.get_position()*1000000 + (self.audio_player.get_duration()*20/180)*1000000)
                    elif event.key == K_DELETE:
                        print self.audio_player.get_paused()
                        if self.audio_player.get_paused(): self.audio_player.play(str(self.audio.uri))
                        else: self.audio_player.pause()

    def destroy(self):
        eventhandler.unsubscribe(self)
        viewport.remove(self._w_track_bar)
        viewport.remove(self._w_track_pos)
        viewport.remove(self._w_time_remaining)
        viewport.remove(self._w_time_played)
